package user.functions;

import user.data.Data;
import guiobjects.Observation;

/**
 * This is the user-created probability function. It must include the public static function probability, which takes two observations i and j and calculates the probability that observations i and j correspond to the same object.
 * 
 * @author Trevor Terris
 *
 */
public class WeightFunction
{	
	private static double beta = 5.0/6.0; 
	private static double gamma = 13.0/6.0; 
	private static double delta = 1.0;
	private static double attributeScalar = 0.6;
	
	public static boolean shouldBeContradictory(Observation i, Observation j)
	{
		return i.camera == j.camera && i.frameNum == j.frameNum && 
					!((i.isEntranceNode && j.isExitNode) ||	(j.isEntranceNode && i.isExitNode));
	}
	
	public static double actualWeight(Observation observationI, Observation observationJ)
	{
    	double xj = observationJ.x; 
    	double zj = observationJ.z;  
    	double tj = (double)observationJ.frameNum;
    	
    	double xi = observationI.x; 
    	double zi = observationI.z;  
    	double ti = (double)observationI.frameNum;
    	
		double power = beta * Math.sqrt(10 * (xj-xi) * (xj-xi) + (zj-zi) * (zj-zi)) + Math.max(0,gamma*(tj - ti - delta));
		
		for (int k = 0; k < observationI.attributes.length; k++)
			power += attributeScalar * Math.abs(observationI.attributes[k] - observationJ.attributes[k]);
		
		double output = Math.exp((-power)*(beta*gamma));
		
		double val = 0.0;
		
		for (int i = 0; i < observationI.attributes.length; i++)
			val += Math.abs(observationI.attributes[i] - observationJ.attributes[i]);
		
//		if (observationI.id == observationJ.id && observationI.frameNum == observationJ.frameNum && output > 0.5)
//			System.out.println(output + " " + observationJ.id + " " + observationJ.frameNum);
		
		//TODO: check this line
		//if (observationJ.frameNum - observationI.frameNum == 1)
		//{
			output -= dummyWeight(observationI, observationJ) * Math.exp((-Math.max(0,gamma*(Math.abs(tj - ti) - delta)))*(beta*gamma));
			output -= dummyWeight(observationJ, observationI) * Math.exp((-Math.max(0,gamma*(Math.abs(tj - ti) - delta)))*(beta*gamma));
		//}
		//if (output < -1 * Data.WEIGHT_CUTOFF)
			//System.out.println(output);
		
		return (Math.abs(output) >= Data.WEIGHT_CUTOFF)?output:0.0;
	}
	public static double dummyWeight(Observation dummy, Observation real)
	{
		double maxDummyWeight = 0.3;
		double camDistance = Data.cameraList.get(dummy.camera).distanceToOutsideCam(real);
		double edgeDistance = Math.min(Math.min(real.x, real.z), Math.min(1-real.x, 1-real.z));
		double minDistance = Math.min(camDistance, edgeDistance);
		if (minDistance < -0.1)
			return maxDummyWeight;
		if (minDistance > 0.1)
			return 0.0;
		return (0.1 - minDistance) * 5 * maxDummyWeight;
	}
}
